﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IWMAG.Scripting.Compiler;
using IWMAG.Scripting.Helpers;
using IWMAG.Scripting.Types;
using IWMAG.Scripting.Compiler.UserInfo;

namespace IWMAG.Scripting.AST.ObjectModel
{
    public abstract class CodeObject
    {
        protected Lexeme From;

        public VariableScopeTreeNode VariableScope { get; private set; }
        public CodeObject(Lexeme from, VariableScopeTreeNode scope = null)
        {
            From = from;
        }

        public abstract void Verify(CompileTable sym, List<IUserInfo> error);

        /// <summary>
        /// Tries to optimize subexpressions, if it returns true, it should be called again.
        /// </summary>
        /// <returns></returns>
        public virtual bool Optimize()
        {
            return false;
        }

        [Obsolete("Use version of SendError that takes a Rules enum instead.")]
        public void SendError(List<IUserInfo> error, string message)
        {
            SendError(false, error, message);
        }


        [Obsolete("Use version of SendError that takes a Rules enum instead.")]
        public void SendError(bool fatal, List<IUserInfo> error, string message)
        {
#pragma warning disable 0618
            error.Add(new CompileError(message, From.Line, From.Column));
#pragma warning restore 0618
            if (fatal)
            {
                throw new VerifyException();
            }
        }


        public void SendError(List<IUserInfo> errorList, Rules ruleViolated, params object[] o)
        {
            SendError(false, errorList, ruleViolated, o);
        }

        public void SendError(bool fatal, List<IUserInfo> errorList, Rules ruleViolated, params object[] o)
        {
            errorList.Add(new CompileError2(ruleViolated, From.Line, From.Column, null, o));


            if (fatal)
            {
                throw new VerifyException();
            }
        }

        public void SendWarning(List<IUserInfo> errorList, Rules ruleViolated, params object[] o)
        {
            errorList.Add(new CompileWarning2(ruleViolated, From.Line, From.Column, null, o));
        }

        
    }

    [Serializable]
    public class VerifyException : Exception {
        public VerifyException() { }
        public VerifyException(string message) : base(message) { }
        public VerifyException(string message, Exception inner) : base(message, inner) { }
        protected VerifyException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }
    }
}
